/**
 * This class implements the tool used to drag and drop a component on the GUI.
 * 
 * @author Gregory Banfi (gregory.banfi@usi.ch); Giuseppe Mendola (giuseppe.mendola@usi.ch);
 * @version 24.05.2011
 */

package ch.usi.inf.pf2.gui;

import java.awt.event.MouseEvent;

import ch.usi.inf.pf2.Component;
import ch.usi.inf.pf2.Wire;
import ch.usi.inf.pf2.Gates.And;
import ch.usi.inf.pf2.Gates.Not;
import ch.usi.inf.pf2.Gates.Or;
import ch.usi.inf.pf2.puts.Input;
import ch.usi.inf.pf2.puts.Output;

public class DragAndDropTool extends Tool {

	private Component selectedComponent;
	private Component componentDragged;
	// private ArrayList<InputPin> inputPins;
	private int connectPosition;

	public DragAndDropTool(Model model) {
		super(model, "Drag And Drop", "cursor.png");
		// inputPins = new ArrayList<InputPin>();
		connectPosition = 15;
	}

	/**
	 * This method responds to the event mousePressed. When the mouse is pressed
	 * it is printed a message on the console, and it finds the component on
	 * which the user has pressed, then depending on what is the component it
	 * creates a new component object with the new coordinates. Finally it adds
	 * the component to the drawing.
	 */
	@Override
	public void mousePressed(final MouseEvent ev) {
		// System.out.println("mousePressed: " + ev);
		final int x = ev.getX();
		final int y = ev.getY();
		selectedComponent = getDrawing().findComponentAt(x, y);
		// System.out.println("mousePressed on " + selectedComponent);
		if (!ev.isShiftDown()) {
			getSelection().clear();
		}
		if (selectedComponent != null) {
			getSelection().add(selectedComponent);
		}
	}

	/**
	 * This method responds to the event mouseDragged. When the mouse was
	 * dragging it is printed a message on the console, then it remove from the
	 * drawing the previous object and creates a component object with the new
	 * coordinates. Finally it adds the component to the drawing.
	 */
	@Override
	public void mouseDragged(final MouseEvent ev) {
		// System.out.println("mouseDragged: " + ev);
		if (selectedComponent != null) {
			getDrawing().remove(componentDragged);
			if (selectedComponent instanceof And) {
				int x = ev.getX() - 15;
				int y = ev.getY() - 15;
				selectedComponent.setOrigin(x, y);
				for (Wire wire : selectedComponent.getInConnectedWires()) {
					if (selectedComponent.hasFreePins()) {
						if (selectedComponent.getFirstFreePin() == 1)
							connectPosition = 15;
					} else if (selectedComponent.getFirstFreePin() == 2) {
						connectPosition = 25;
					}
					wire.setFinalPoint(selectedComponent.getOriginX() - 5,
							selectedComponent.getOriginY() + connectPosition);
				}
				for (Wire wire : selectedComponent.getOutConnectedWires()) {
					wire.setStartPoint(selectedComponent.getOriginX() + 40,
							selectedComponent.getOriginY() + 20);
				}

			} else if (selectedComponent instanceof Not) {
				selectedComponent.setOrigin(ev.getX()-15, ev.getY()-15);
				for (Wire wire : selectedComponent.getInConnectedWires()) {
					wire.setFinalPoint(selectedComponent.getOriginX() - 5,
							selectedComponent.getOriginY() + 20);
				}

				for (Wire wire : selectedComponent.getOutConnectedWires()) {
					wire.setStartPoint(selectedComponent.getOriginX() + 40,
							selectedComponent.getOriginY() + 20);
				}

			} else if (selectedComponent instanceof Or) {
				selectedComponent.setOrigin(ev.getX() - 60, ev.getY() - 20);
				for (Wire wire : selectedComponent.getInConnectedWires()) {
					if (selectedComponent.hasFreePins()) {
						if (selectedComponent.getFirstFreePin() == 1)
							connectPosition = 15;
					} else if (selectedComponent.getFirstFreePin() == 2) {
						connectPosition = 25;
					}
					wire.setFinalPoint(selectedComponent.getOriginX() + 45,
							selectedComponent.getOriginY() + connectPosition);
				}
				for (Wire wire : selectedComponent.getOutConnectedWires()) {
					wire.setStartPoint(selectedComponent.getOriginX() + 95,
							selectedComponent.getOriginY() + 20);
				}

			} else if (selectedComponent instanceof Input) {
				selectedComponent.setOrigin(ev.getX()+2, ev.getY()+2);
				for (Wire wire : selectedComponent.getOutConnectedWires()) {
					wire.setStartPoint(selectedComponent.getOriginX() + 23,
							selectedComponent.getOriginY() + 10);
				}

			} else if (selectedComponent instanceof Output) {
				selectedComponent.setOrigin(ev.getX()+2, ev.getY()+2);
				for (Wire wire : selectedComponent.getInConnectedWires()) {
					wire.setFinalPoint(selectedComponent.getOriginX() - 3,
							selectedComponent.getOriginY() + 10);
				}
			}
			getDrawing().add(selectedComponent);
		}
	}

	/**
	 * This method responds to the event mouseReleased. When the mouse is
	 * released it is printed a message on the console, and the previous
	 * component is removed, and it draw an final component to the final
	 * coordinates. Finally it adds the component to the drawing.
	 */
	@Override
	public void mouseReleased(final MouseEvent ev) {
		// System.out.println("mouseReleased: " + ev);
		if (selectedComponent != null) {
			getDrawing().remove(componentDragged);
			if (selectedComponent instanceof And) {
				int x = ev.getX() - 15;
				int y = ev.getY() - 15;
				selectedComponent.setOrigin(x, y);
				for (Wire wire : selectedComponent.getInConnectedWires()) {
					if (selectedComponent.hasFreePins()) {
						if (selectedComponent.getFirstFreePin() == 1)
							connectPosition = 15;
					} else if (selectedComponent.getFirstFreePin() == 2) {
						connectPosition = 25;
					}
					wire.setFinalPoint(selectedComponent.getOriginX() - 5,
							selectedComponent.getOriginY() + connectPosition);
				}
				for (Wire wire : selectedComponent.getOutConnectedWires()) {
					wire.setStartPoint(selectedComponent.getOriginX() + 40,
							selectedComponent.getOriginY() + 20);
				}
			} else if (selectedComponent instanceof Not) {
				selectedComponent.setOrigin(ev.getX()-15, ev.getY()-15);
				for (Wire wire : selectedComponent.getInConnectedWires()) {
					wire.setFinalPoint(selectedComponent.getOriginX() - 5,
							selectedComponent.getOriginY() + 20);
				}

				for (Wire wire : selectedComponent.getOutConnectedWires()) {
					wire.setStartPoint(selectedComponent.getOriginX() + 40,
							selectedComponent.getOriginY() + 20);
				}
			} else if (selectedComponent instanceof Or) {
				selectedComponent.setOrigin(ev.getX() - 60, ev.getY() - 20);
				for (Wire wire : selectedComponent.getInConnectedWires()) {
					if (selectedComponent.hasFreePins()) {
						if (selectedComponent.getFirstFreePin() == 1)
							connectPosition = 15;
					} else if (selectedComponent.getFirstFreePin() == 2) {
						connectPosition = 25;
					}
					wire.setFinalPoint(selectedComponent.getOriginX() + 45,
							selectedComponent.getOriginY() + connectPosition);
				}
				for (Wire wire : selectedComponent.getOutConnectedWires()) {
					wire.setStartPoint(selectedComponent.getOriginX() + 95,
							selectedComponent.getOriginY() + 20);
				}

			} else if (selectedComponent instanceof Input) {
				selectedComponent.setOrigin(ev.getX()+2, ev.getY()+2);
				for (Wire wire : selectedComponent.getOutConnectedWires()) {
					wire.setStartPoint(selectedComponent.getOriginX() + 23,
							selectedComponent.getOriginY() + 10);
				}

			} else if (selectedComponent instanceof Output) {
				selectedComponent.setOrigin(ev.getX()+2, ev.getY()+2);
				for (Wire wire : selectedComponent.getInConnectedWires()) {
					wire.setFinalPoint(selectedComponent.getOriginX() - 3,
							selectedComponent.getOriginY() + 10);
				}

			}
		}

		getDrawing().add(selectedComponent);
		getSelection().clear();
		getSelection().add(selectedComponent);

	}
}
